import { CanvasSource} from "pixi.js";
import { Sprite } from "@/sprites/Sprite.js";
import { ImageManager } from "@/managers/ImageManager.js";
import { ToneFilter } from "@/filters/ToneFilter.js";
export class Sprite_Canvas extends Sprite{
    constructor(width,height){
        let canvasSource=new CanvasSource({width,height});
        super(canvasSource);

        this.canvasSource=canvasSource;
        this._context=this.canvasSource.context2D;
        this._context.font='28px GameFont';
        this._fontSize=28;
        this._fontItalic = false;
        this.textColor = '#ffffff';
        this.outlineColor = '#000000';
        this.outlineWidth = 4;

        this.toneFilter=null;

        this.dirty=false;
        this.redraw=false;
    }

    set fontSize(value){
        if(this._fontSize==value)return;
        this._fontSize=value;
        this._context.font=`${value}px GameFont`;
    }
    get fontSize(){return this._fontSize;}
    set fontItalic(value){
        if(this._fontItalic==value)return;
        this._fontSize=value;
        if(this._fontSize){
            this._context.font=`Italic ${this._fontSize}px GameFont`;
        }else{
            this._context.font=`${this._fontSize}px GameFont`;
        }
    }
    get fontItalic(){return this._fontItalic;}

    set paintOpacity(value) {
      this._context.globalAlpha = value / 255;
    }
    get paintOpacity(){
        return this._context.globalAlpha*255;
    }

    setDirty(){
        this.dirty=true;
        this.redraw=true;
    }

    resize(width,height){
        if(this.canvasSource.width!=width||this.canvasSource.height!=height){
            if(!this.dirty
                ||(this.canvasSource.width>width
                    &&this.canvasSource.height>height)){
                this.canvasSource.resize(width,height);
                this.updateTexture();
                return;
            }
            let canvasSource=new CanvasSource({width,height});
            let context2D=canvasSource.context2D;
            let drawWidth=Math.min(this.canvasSource.width,width);
            let drawHeight=Math.min(this.canvasSource.height,height);
            context2D.drawImage(this.canvasSource.resource,0,0,drawWidth,drawHeight,0,0,drawWidth,drawHeight);
            
            this.texture.source=canvasSource;
            this.updateTexture();

            context2D.font=this._context.font;
            context2D.globalAlpha=this._context.globalAlpha;

            this.canvasSource.destroy();
            this.canvasSource=canvasSource;
            this._context=context2D;

            this.dirty=false;
        }
    }

    adjustTone(r,g,b){
        if(r!=0||g!=0||b!=0){
            if(!this.toneFilter){
                this.toneFilter=new ToneFilter();
                this.filters=[this.toneFilter];
            }else{
                this.toneFilter.enabled=true;
            }
            this.toneFilter.setTone(r/255,g/255,b/255);
        }else if(this.toneFilter){
            this.toneFilter.enabled=false;
        }
    }

    measureTextWidth(text){
        return this._context.measureText(text).width;
    }

    drawText(text,x,y, maxWidth, lineHeight, align){
        if (text) {
            let tx = x;
            let ty = y + 0.5*lineHeight+this.fontSize * 0.35;
            let context = this._context;
            let alpha = context.globalAlpha;
            context.save();
            maxWidth = maxWidth??0xffff;
            if(align=='right'){
                tx+=(maxWidth-this._context.measureText(text).width);
            }else if(align=='center'){
                tx+=(maxWidth-this._context.measureText(text).width)/2;
            }
            context.textAlign = 'left';
            context.globalAlpha = 1;
            this._drawTextOutline(text, tx, ty, maxWidth);
            context.globalAlpha = alpha;
            this._drawTextBody(text, tx, ty, maxWidth);
            context.restore();

            this.setDirty();
        }
    }

    _drawTextOutline(text, tx, ty, maxWidth) {
        let context = this._context;
        context.strokeStyle = this.outlineColor;
        context.lineWidth = this.outlineWidth;
        context.lineJoin = 'round';
        context.strokeText(text, tx, ty, maxWidth);
    }

    _drawTextBody(text, tx, ty, maxWidth) {
        let context = this._context;
        context.fillStyle = this.textColor;
        context.fillText(text, tx, ty, maxWidth);
    }

    enlargeFont(){
        let fontSize=this._fontSize+12;
        if(fontSize<=96){
            this.fontSize=fontSize;
        }
    }
    reduceFont(){
        let fontSize=this._fontSize-12;
        if(fontSize>=24){
            this.fontSize=fontSize;
        }
    }

    blt(resource,sx,sy,sw,sh,dx,dy,dw,dh){
        this._context.drawImage(resource,sx,sy,sw,sh,dx,dy,dw??sw,dh??sh);
        this.setDirty();
    }

    drawIcon(index,iconSize,x,y){
        ImageManager.loadSystem('IconSet').then(source=>{
            let xi=index%16;
            let yi=(index-xi)/16;
            let size=iconSize;
            this._context.drawImage(
                source.resource,
                xi*size,
                yi*size,
                size,size,
                x,y,size,size
            );
            ImageManager.releaseSystem('IconSet');
            this.setDirty();
        });
    }

    drawLine(x,y,dx,dy,color,width){
        this._context.save();
        this._context.strokeStyle=color??'#000';
        this._context.lineWidth=width??4;
        this._context.moveTo(x,y);
        this._context.lineTo(dx,dy);
        this._context.stroke();
        this._context.restore();

        this.setDirty();
    }

    drawCircle(x, y, radius, color) {
        let context = this._context;
        context.save();
        context.fillStyle = color;
        context.beginPath();
        context.arc(x, y, radius, 0, Math.PI * 2, false);
        context.fill();
        context.restore();

        this.setDirty();
    }

    
    clearRect(x, y, width, height) {
        this._context.clearRect(x, y, width, height);
        this.setDirty();
    }

    fillRect(x, y, width, height, color) {
        let context = this._context;
        context.save();
        context.fillStyle = color;
        context.fillRect(x, y, width, height);
        context.restore();

       this.setDirty();
    }

    gradientFillRect(x, y, width, height, color1, color2, vertical) {
        let context = this._context;
        let grad=null;
        if (vertical) {
            grad = context.createLinearGradient(x, y, x, y + height);
        } else {
            grad = context.createLinearGradient(x, y, x + width, y);
        }
        grad.addColorStop(0, color1);
        grad.addColorStop(1, color2);
        context.save();
        context.fillStyle = grad;
        context.fillRect(x, y, width, height);
        context.restore();

        this.setDirty();
    }

    fillAll(color) {
        this.fillRect(0, 0, this.canvasSource.width, this.canvasSource.height, color);
    }

    clear() {
        this.clearRect(0, 0,  this.canvasSource.width, this.canvasSource.height);
    }

    releaseTextureSource(){
        this.canvasSource.destroy();
        this.canvasSource=null;
        this._context=null;
    }

    update(){
        super.update();
        if(this.redraw){
            this.redraw=false;
            this.canvasSource.update();
        }
    }
}